package game;

import java.awt.*;
import java.awt.event.*;
import java.net.*;
import java.io.*;

import javax.imageio.ImageIO;
import javax.swing.*;
/*
 * main class
 */
public class Game extends Thread implements ActionListener,Runnable {
	private String action;
	@SuppressWarnings("unused")
	private int gamestage;
	private int[] cards;
	private boolean[] exchangecards;
	private boolean ingame;
	
	private BadugiServer s;
	private Socket socket;
	private String myname;
	private BufferedReader reader;
	private PrintWriter writer;
	private Timer t;
	
	private JFrame mainframe;
	private JPanel mainscreen;
	private JPanel buttons;
	private JPanel myinfo;
	private JLabel info;
	private JPanel[] cardex;
	private JLabel[] card;
	private JLabel mytokens;
	private JLabel mybet;
	private Image[] cardimages;
	
	private JPanel[] playerinfo;
	/* 0=name
	 * 1=number of tokens
	 * 2=actual bet
	 * 3=last exchange
	 * 4=last action
	 */
	private JLabel[] playerlabels;
	private boolean[] playersingame;
	
	private JButton newgame;
	private JButton joingame;
	private JButton exitgame;
	private JButton fold;
	private JButton raise;
	private JButton check;
	private JButton bet;
	private JButton allin;
	private JButton command;
	private JButton back;
	private JButton call;
	private JButton[] exchangecard;
	private JButton exchange;
	private GridBagConstraints c;
	
	public Game() {
		action="";
		ingame=false;
		mybet=new JLabel();
		playersingame=new boolean[5];
		for (int i=0;i<5;i++) {
			playersingame[i]=false;
		}
		s=new BadugiServer();
		try {
			t=new Timer(50);
		} catch (BadugiException e) {
		}
		cards=new int[4];
		exchangecards=new boolean[4];
		for (int i=0;i<4;i++) {
			exchangecards[i]=false;
			cards[i]=0;
		}
		
		cardimages=new Image[52];
		for (int i=0;i<52;i++) {
			try {
				cardimages[i]=ImageIO.read(new File("Data/"+i+".jpg"));
			} catch (IOException e) {
			}
		}
		
		mainframe=new JFrame("Badugi");
		mainscreen=new JPanel();
		buttons=new JPanel();
		myinfo=new JPanel();
		info=new JLabel();
		mytokens=new JLabel();
		playerinfo=new JPanel[5];
		cardex=new JPanel[4];
		card=new JLabel[4];
		playerlabels=new JLabel[25];
		for(int i=0; i<25;i++){
			playerlabels[i]=new JLabel();
		}
		for (int i=0;i<5;i++) {
			playerinfo[i]=new JPanel();
		}
		for (int i=0;i<4;i++) {
			cardex[i]=new JPanel();
			card[i]=new JLabel();
		}
		c=new GridBagConstraints();
		
		newgame=new JButton("New game");
		joingame=new JButton("Join game");
		exitgame=new JButton("Exit game");
		fold=new JButton("Fold");
		raise=new JButton("Raise");
		check=new JButton("Check");
		bet=new JButton("Bet");
		allin=new JButton("All In");
		command=new JButton("Admin command");
		back=new JButton("Back to main menu");
		call=new JButton("Call");
		exchangecard=new JButton[4];
		for (int i=0;i<4;i++) {
			exchangecard[i]=new JButton(i+"");
			exchangecard[i].setActionCommand("exchange"+i);
			exchangecard[i].addActionListener(this);
		}
		exchange=new JButton("Exchange cards");
		
		newgame.setActionCommand("newgame");
		joingame.setActionCommand("joingame");
		exitgame.setActionCommand("exitgame");
		fold.setActionCommand("fold");
		raise.setActionCommand("raise");
		check.setActionCommand("check");
		bet.setActionCommand("bet");
		allin.setActionCommand("allin");
		command.setActionCommand("command");
		back.setActionCommand("back");
		call.setActionCommand("call");
		exchange.setActionCommand("exchange");
		
		newgame.addActionListener(this);
		joingame.addActionListener(this);
		exitgame.addActionListener(this);
		fold.addActionListener(this);
		raise.addActionListener(this);
		check.addActionListener(this);
		bet.addActionListener(this);
		allin.addActionListener(this);
		command.addActionListener(this);
		back.addActionListener(this);
		call.addActionListener(this);
		exchange.addActionListener(this);
		
		mainframe.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		mainframe.setSize(640, 480);
		mainframe.setLayout(new BorderLayout());
		mainframe.add(mainscreen,BorderLayout.CENTER);
		mainframe.add(buttons,BorderLayout.PAGE_END);
		buttons.setLayout(new GridBagLayout());
		c.fill=GridBagConstraints.HORIZONTAL;
		c.ipady=20;
		c.weightx=0.5; 
		c.weighty=1;
		c.gridheight=1;
		c.gridy=0;
		c.gridx=0;
		buttons.add(newgame,c);
		c.gridx=1;
		buttons.add(joingame,c);
		c.gridx=2;
		buttons.add(exitgame,c);
		mainscreen.setLayout(new GridLayout(2,3));
		mainscreen.add(playerinfo[1]);
		mainscreen.add(playerinfo[2]);
		mainscreen.add(playerinfo[3]);
		mainscreen.add(playerinfo[4]);
		mainscreen.add(myinfo);
		mainscreen.add(playerinfo[0]);
		for(int i=0;i<5;i++){
			playerinfo[i].setLayout(new GridLayout(5,1));
			for(int j=0;j<5;j++){
				playerinfo[i].add(playerlabels[5*i+j]);
			}
		}
		
		myinfo.setLayout(new GridBagLayout());
		c.ipadx=1;
		c.gridx=0;
		c.gridy=0;
		c.gridwidth=4;
		myinfo.add(mytokens, c);
		c.gridy++;
		myinfo.add(mybet,c);
		c.gridy++;
		myinfo.add(info, c);
		c.gridy++;
		myinfo.add(exchange, c);
		c.gridy++;
		c.gridwidth=1;
		for (int i=0;i<4;i++) {
			c.gridx=i;
			myinfo.add(cardex[i], c);
		}
		c.gridy++;
		for (int i=0;i<4;i++) {
			c.gridx=i;
			myinfo.add(card[i], c);
		}
		c.gridy++;
		for (int i=0;i<4;i++) {
			c.gridx=i;
			myinfo.add(exchangecard[i], c);
		}
		mainframe.setVisible(true);
		myname=JOptionPane.showInputDialog(mainframe,"Enter your name:",null);
		c.gridy=0;
	}
	
	/*
	 * main function, creating new window with game
	 */
	public static void main(String[] args) {
		Game game=new Game();
		game.s.start();
		game.t.start();
		game.start();
		while(!(game.action.equals("exitgame"))) {
			if(game.t.frames>0) {
				if (game.action.equals("joingame")) {//joining game
					game.action="";
					game.buttons.remove(game.newgame);
					game.buttons.remove(game.joingame);
					game.buttons.remove(game.exitgame);
					game.c.gridx=0;
					game.buttons.add(game.fold,game.c);
					game.c.gridx++;
					game.buttons.add(game.bet,game.c);
					game.c.gridx++;
					game.buttons.add(game.check,game.c);
					game.c.gridx++;
					game.buttons.add(game.raise,game.c);
					game.c.gridx++;
					game.buttons.add(game.call,game.c);
					game.c.gridx++;
					game.buttons.add(game.allin,game.c);
					game.c.gridx++;
					game.buttons.add(game.back,game.c);
					game.buttons.validate();
					game.buttons.repaint();
					String ip=JOptionPane.showInputDialog(game.mainframe,"Enter IP to connect to:",null);
					try {
						game.socket=new Socket(ip,BadugiServer.port);
						game.writer=new PrintWriter(game.socket.getOutputStream(), true);
						game.reader=new BufferedReader(new InputStreamReader(game.socket.getInputStream()));
						game.writer.println(game.myname);
					} catch (IOException e) {
					}
					game.ingame=true;
					game.mytokens.setText("10000 tokens");
					while(!(game.action.equals("back"))) {//you play game you joined
						if (game.t.frames>0) {
							game.TryAction();
						}
						try {
							sleep(1);
						} catch (InterruptedException e) {
						}
					}
					game.ingame=false;
					game.writer.println("Q");
					for (int i=0;i<25;i++) {
						game.playerlabels[i].setText("");
					}
					game.action="";
					game.buttons.remove(game.fold);
					game.buttons.remove(game.bet);
					game.buttons.remove(game.check);
					game.buttons.remove(game.raise);
					game.buttons.remove(game.call);
					game.buttons.remove(game.allin);
					game.buttons.remove(game.back);
					game.c.gridx=0;
					game.buttons.add(game.newgame,game.c);
					game.c.gridx=1;
					game.buttons.add(game.joingame,game.c);
					game.c.gridx=2;
					game.buttons.add(game.exitgame,game.c);
					game.buttons.validate();
					game.buttons.repaint();
				} else if (game.action.equals("newgame")) {//creating own game
					game.action="";
					game.buttons.remove(game.newgame);
					game.buttons.remove(game.joingame);
					game.buttons.remove(game.exitgame);
					game.c.gridx=0;
					game.buttons.add(game.fold,game.c);
					game.c.gridx++;
					game.buttons.add(game.bet,game.c);
					game.c.gridx++;
					game.buttons.add(game.check,game.c);
					game.c.gridx++;
					game.buttons.add(game.raise,game.c);
					game.c.gridx++;
					game.buttons.add(game.call,game.c);
					game.c.gridx++;
					game.buttons.add(game.allin,game.c);
					game.c.gridx++;
					game.buttons.add(game.command,game.c);
					game.c.gridx++;
					game.buttons.add(game.back,game.c);
					game.buttons.validate();
					game.buttons.repaint();
					game.info.setText("game ready");
					game.mytokens.setText("10000 tokens");
					try {
						game.socket=new Socket("localhost",BadugiServer.port);
						game.writer=new PrintWriter(game.socket.getOutputStream(), true);
						game.reader=new BufferedReader(new InputStreamReader(game.socket.getInputStream()));
						game.writer.println(game.myname);
					} catch (IOException e) {
					}
					game.ingame=true;
					while(!(game.action.equals("back"))) {//you play game you joined
						if(game.t.frames>0) {
								game.TryAction();
						} else {
							try {
								sleep(1);
							} catch (InterruptedException e) {
							}
						}
					}
					game.ingame=false;
					game.action="";
					game.writer.println("Q");
					for (int i=0;i<25;i++) {
						game.playerlabels[i].setText("");
					}
					game.buttons.remove(game.fold);
					game.buttons.remove(game.bet);
					game.buttons.remove(game.check);
					game.buttons.remove(game.raise);
					game.buttons.remove(game.call);
					game.buttons.remove(game.allin);
					game.buttons.remove(game.command);
					game.buttons.remove(game.back);
					game.c.gridx=0;
					game.buttons.add(game.newgame,game.c);
					game.c.gridx=1;
					game.buttons.add(game.joingame,game.c);
					game.c.gridx=2;
					game.buttons.add(game.exitgame,game.c);
					game.buttons.validate();
					game.buttons.repaint();
				}
			} else {
				try {
					sleep(1);
				} catch (InterruptedException e) {
				}
			}
		}
		System.exit(1);
	}
	
	@Override
	public void actionPerformed(ActionEvent e) {
		action=e.getActionCommand();
	}
	
	@Override
	public void run() {
		String input;
		while(true) {
			if (ingame)
			{
				int ID;
				try {
					input=reader.readLine();
					if(input.equals("Y")) {//your turn
						gamestage=0;
						info.setText("Your turn");
					}
					try {
						ID=Integer.parseInt(input.substring(1,2));
					} catch (StringIndexOutOfBoundsException e) {
						ID=7;
					} catch (NumberFormatException e) {
						ID=7;
					}
					if (input.substring(0,1).equals("K")) {//cards
						cards[ID]=Integer.parseInt(input.substring(2));
						try {
							card[ID].setText(Deck.CardName(cards[ID]));
						} catch (BadugiException e) {
						}
					}
					if (input.substring(0,1).equals("M")) {//cards
						info.setText(input.substring(1));
					}
					if (input.substring(0,1).equals("L")) {//set info
						if (ID==5) {
							int ID2=Integer.parseInt(input.substring(2,3));
							if (ID2==1) {
								mytokens.setText(input.substring(3));
							} else if (ID2==2) {
								mybet.setText(input.substring(3));
							}
						} else {
							playerlabels[ID*5+Integer.parseInt(input.substring(2,3))].setText(input.substring(3));
						}
					}
				} catch (IOException e) {
				}
			}
			try {
				sleep(1);
			} catch (InterruptedException e) {
			}
		}
	}
	
	private void TryAction() {
		t.frames--;
		if(action.equals("fold")) {
			info.setText(action);
			writer.println("B");
			action="";
		} else if (action.equals("raise")) {
			info.setText(action);
			writer.println("F"+JOptionPane.showInputDialog(mainframe,"Raise by:",null));
			action="";
		} else if (action.equals("bet")) {
			info.setText(action);
			writer.println("D"+JOptionPane.showInputDialog(mainframe,"Bet:",null));
			action="";
		} else if (action.equals("allin")) {
			info.setText(action);
			writer.println("H");
			action="";
		} else if (action.equals("check")) {
			info.setText(action);
			writer.println("C");
			action="";
		} else if (action.equals("call")) {
			info.setText(action);
			writer.println("G");
			action="";
		} else if (action.equals("command")) {
			info.setText(action);
			writer.println("E"+JOptionPane.showInputDialog(mainframe,"Command:",null));
			action="";
		} else if (action.equals("exchange")) {
			info.setText(action);
			String message="I";
			for (int i=0;i<4;i++) {
				if (exchangecards[i]) message+="Y";
				else message+="N";
			}
			writer.println(message);
			action="";
		} else for (int i=0;i<4;i++) {
			if (action.equals("exchange"+i)) {
				exchangecards[i]=!(exchangecards[i]);
				if (exchangecards[i]) {
					cardex[i].repaint();
					cardex[i].getGraphics().drawImage(cardimages[cards[i]], 0, 0, null);
					cardex[i].getGraphics().drawImage(cardimages[cards[i]], 0, 0, null);
					card[i].setText(" ");
				} else {
					cardex[i].repaint();
					try {
						card[i].setText(Deck.CardName(cards[i]));
					} catch (BadugiException e) {
					}
				}
				action="";
			}
		}
	}
}
